#pragma once
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <atomic>
#include <thread>
#include <sys/time.h>
#include <boost/algorithm/string.hpp>

namespace ns_util
{

    class TimeUtil
    {
    public:
        static std::string GetNowTimeday()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            return std::to_string(_time.tv_sec);
        }
        static std::string GetTimeMs()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            // 获取毫秒，秒*1000 + 微秒/1000。
            return std::to_string(_time.tv_sec * 1000 + _time.tv_usec / 1000);
        }
    };
    class PathUtil
    {
    public:
        static std::string AddSuffixSrc(const std::string &file_name)
        {
            std::string src_file = file_name;
            src_file += ".cc";
            return src_file;
        }
        static std::string AddSuffixComErr(const std::string &file_name)
        {
            std::string com_err_file = file_name;
            com_err_file += "ComErr";
            return com_err_file;
        }
        static std::string AddSuffixStdin(const std::string &file_name)
        {
            std::string stdin_file = file_name;
            stdin_file += "Stdin";
            return stdin_file;
        }
        static std::string AddSuffixStdout(const std::string &file_name)
        {
            std::string stdout_file = file_name;
            stdout_file += "Stdout";
            return stdout_file;
        }
        static std::string AddSuffixStderr(const std::string &file_name)
        {
            std::string stderr_file = file_name;
            stderr_file += "Stderr";
            return stderr_file;
        }
        // 毫秒级时钟+原子性变量 确保唯一性
        static std::string GetUniqueName()
        {
            static std::atomic_uint id(0);
            std::string ms = TimeUtil::GetTimeMs();
            std::string _id = std::to_string(id);
            ++id;
            return ms + "_" + _id;
        }
    };
    class FileUtil
    {
    public:
        /***************************
         * str:输出形参数，将读取文件内容存储位置
         * file_path:输入形参数，读取文件的路径
         * raw:输入形参数，是否保持文件原貌(默认true:保留\n等)
         **************************/
        static void ReadFile(std::string &str, const std::string &file_path, bool raw = true)
        {
            std::ifstream ifst(file_path);
            std::string line;
            while (std::getline(ifst, line))
            {
                if (raw)
                    line += "\n";
                str += line;
            }
            ifst.close();
        }
        /***************************
         * v:输出形参数，将读取文件内容按行存储
         * file_path:输入形参数，读取文件的路径
         **************************/
        static void ReadLineFile(std::vector<std::string> &v, const std::string &file_path)
        {
            std::ifstream ifst(file_path);
            std::string line;
            while (std::getline(ifst, line))
            {
                v.push_back(line);
            }
            ifst.close();
        }
        static void WriteFile(const std::string code, const std::string &file_path)
        {
            std::ofstream ofst;
            ofst.open(file_path, std::ofstream::out | std::ofstream::trunc);
            ofst << code;
            ofst.close();
        }
        static void DeleFile(const std::string file_path)
        {
            struct stat buff;
            if (stat(file_path.c_str(), &buff) == 0)
            {
                // remove(file_path.c_str());
                unlink(file_path.c_str());
            }
        }
    };
    class StrUtil
    {
    public:
        /***************************
         * blanks:输出形参数，切分的字符串存储到此处
         * souce:输入形参数，需要切分的字符串
         * sep:切分的分割符
         * raw:是否需要压缩空字符块(默认ture需要)
         **************************/
        static bool SplitString(std::vector<std::string> &blanks,
                                const std::string &souce, const std::string &sep, bool raw = true)
        {
            // /boost::algorithm::token_compress_on 压缩空字符串
            raw ? boost::split(blanks, souce, boost::is_any_of(sep), boost::algorithm::token_compress_on) 
            : boost::split(blanks, souce, boost::is_any_of(sep), boost::algorithm::token_compress_off);

            return blanks.size() == 0 ? false : true;
        }
    };

}